package org.shell;

import java.util.Arrays;
import org.shell.commands.Command;
import org.shell.commands.CommandInvoker;
import org.shell.commands.CommandsHolder;
import org.shell.commands.ShellCommand;
import org.shell.loaders.JarLoader;
import org.shell.loaders.Loader;
import org.shell.loaders.annotations.CommandMethod;
import org.shell.loaders.exceptions.LoaderGeneralException;
import org.shell.utils.config.ConfigManager;

public class SystemCommands {

    private static StringBuilder b;

    @CommandMethod(name = "exit", description = "exit shell")
    public static void exit() {
        System.exit(0);
    }

    @CommandMethod(name = "instances", description = "lists all instances")
    public static String showInstances() {
        b = new StringBuilder();
        b.append("Class instances:\n");
        for (Object instance : CommandInvoker.showInstances()) {
            b.append(instance + "\n");
        }
        return b.toString();
    }

    @CommandMethod(name = "threads", description = "lists all threads")
    public static String listThreads() {
        b = new StringBuilder();
        b.append(ThreadsManager.listThreads());
        return b.toString();
    }

    @CommandMethod(name = "kill", description = "kills selected thread")
    public static String listThreads(String Sid) {
        b = new StringBuilder();
        long id = Long.valueOf(Sid);
        boolean result = ThreadsManager.killThread(id);
        if (result) {
            b.append("Thread killed\n");
        } else {
            b.append("Thread doesnt exists\n");
        }
        return b.toString();
    }

    @CommandMethod(name = "iremove", description = "removes instance")
    public static String delInstance(String name) {
        b = new StringBuilder();
        CommandInvoker.remove(name);
        return b.toString();
    }

    @CommandMethod(name = "help", description = "lists all commands")
    public static String help() {
        int columnFirst = 15;
        b = new StringBuilder();
        b.append("Available commands:\n");
        Command commands[] = CommandsHolder.getCommands().toArray(new Command[1]);
        Arrays.sort(commands);
        for (Command command : commands) {
            b.append(((ShellCommand) command).getCommandName());
            for (int i = ((ShellCommand) command).getCommandName().length(); i < columnFirst; i++) {
                b.append(" ");
            }
            b.append(" - ");
            b.append(((ShellCommand) command).getDescription());
            b.append("\n");
        }
        return b.toString();
    }

    @CommandMethod(name = "load", description = "load external JAR file;\n"
    + "                  Available parameters:\n"
            + "                   -f loads all jars in folder\n"
            + "                   -o overwrite flag")
    public static String loadJar(String ... params) {
        b = new StringBuilder();
        String path = null;
        boolean dirFlag = false;
        boolean overwriteFlag = false;
        for(String param : params) {
            if(param.startsWith("-")) {
                if(param.equals("-f")) {
                    dirFlag = true;
                } else if(param.startsWith("-o")) {
                    overwriteFlag = true;
                } else {
                    b.append("Unknown param: ").append(param);
                    return b.toString();
                }
            } else {
                path = param;
            }
        }
        Loader loader = new JarLoader();
        try {
            loader.load(path, overwriteFlag);
            b.append("Jar loaded");
        } catch (LoaderGeneralException ex) {
            b.append("Cant load jar: ").append(ex.getLocalizedMessage());
        }
        return b.toString();
    }

    @CommandMethod(name = "set", description = "sets parameter")
    public static String setParam(String name, Object value) {
        b = new StringBuilder();
        ConfigManager.set(name, value);
        b.append(name + "=" + value);
        return b.toString();
    }

    @CommandMethod(name = "get", description = "gets parameter")
    public static String getParam(String name) {
        b = new StringBuilder();
        b.append(ConfigManager.get(name));
        return b.toString();
    }

    @CommandMethod(name = "params", description = "lists all parameters")
    public static String list() {
        b = new StringBuilder();
        b.append(Arrays.deepToString(ConfigManager.list()));
        return b.toString();
    }
}
